﻿/*********************************************************************
 *
 *                             NOTICE
 *               COPYRIGHT (c) 2012 Panoscopix Software, Inc.
 *                UNPUBLISHED - ALL RIGHTS RESERVED
 * 
 *      This program is confidential, proprietary, and a trade
 *   secret of Panoscopix Software, Inc. The receipt or possession of
 *     this program does not convey any rights to reproduce or
 *      disclose its contents, or to manufacture, use, or sell
 *       anything that it may describe, in whole or in part, 
 *   without the specific written consent of Panoscopix Software, Inc.
 *
 * Command class for "touching" a file, i.e., creating a file.
 * 
 *******************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using FileSystem;
using FileSystem.Utility;

namespace FileSystem.Impl.Commands
{
	class AppendCommand : ICommand, ICommandPrototype, INodeVisitor
	{
        private static AppendCommand zombie;
	
		private static void loadEmulator() {
            zombie = new AppendCommand(new HelpDescription() { Name = "append", Description = "Appends text to a file." });
			ICommandPrototypeRegistry r = AppResources.getInstance().getCommandRegistry();
			r.register("append", zombie);
		}
        public IHelpDescription Description
        {
            get;
            private set;
        }
		private string fileName;
        private IFSFile file;
		private String contents;
		private bool executeSucceeded;
		private IResult lastResult;
        private IFSDirectory directory;
        private int writeIndex;

        private AppendCommand(IHelpDescription helpDescription)
        {
			//for zombie
            this.Description = helpDescription;
		}

        private AppendCommand(string fileName, String contents)
		{
            this.fileName = fileName;
			this.contents = contents;
            executeSucceeded = false;
		}
	
		public ICommand clone() {
            return new AppendCommand(this.fileName, this.contents);
		}
	
		public ICommand clone(String arg) {
            string fileName = StringUtil.firstToken(arg);
            string contents = StringUtil.remainder(arg);
            AppendCommand rc = new AppendCommand(fileName, contents);
			return rc;
		}

		public IResult execute() {
            this.directory = AppResources.getInstance().getFileSystem().CurrentDirectory;
			IFSNode node = directory.GetByName(this.fileName);
			lastResult = null;
			executeSucceeded = false;

			if (node != null)
			{
				node.Accept(this);
			}
			else
			{
				lastResult = new Result(true, "Given file could not be found.");
			}

			return lastResult;
		}
	
		public void undo() {
			if (!executeSucceeded) {
				//nothing to do, because execution failed...
				//we don't want to remove the node that might have been there of the same name.
				return;
			}

            string allContents = this.file.getContents();
            allContents = allContents.Remove(this.writeIndex);
            this.file.setContents(allContents);
            
		}
	
		public IResult redo() {
			return execute();
		}
	
		public String describe(IPrintContext context) {
			return context.getFormattedString("append " + fileName + "(" + executeSucceeded + ").");
		}

		#region INodeVisitor Members

		public void VisitFile(IFSFile file)
		{
            this.file = file;
            this.writeIndex = this.file.getSize();
            this.file.appendContents(this.contents);
            lastResult = new Result("File append was successful!");
			executeSucceeded = true;
		}

		public void VisitDirectory(IFSDirectory directory)
		{
            lastResult = new Result(true, "Given name is not a file");
            executeSucceeded = false;
		}

		public void VisitLink(IFSLink link)
		{
			if (link.GetLinkedNode() != null)
			link.GetLinkedNode().Accept(this);
		}

		#endregion
	}
}
